package com.qd.panda.service.park;

import com.cdqidi.constant.ConstantDto;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.ServletUtil;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.carpark.CarParkInfoDTO;
import com.qd.common.panda.domain.entity.carpark.PersonCarPark;
import com.qd.common.panda.domain.entity.score.CarParkEvaluateDTO;
import com.qd.common.panda.domain.entity.stroke.HistoryStrokeVO;
import com.qd.common.panda.domain.entity.stroke.UserStrokeHistoryDTO;
import com.qd.common.sys.domain.login.LoginUser;
import com.qd.hik.dto.HkBaseHttpResp;
import com.qd.hik.dto.parkinfo.HkParkInfoResp;
import com.qd.hik.service.HkParkInfoService;
import com.qd.panda.model.CarPark;
import com.qd.panda.model.UserCollect;
import com.qd.panda.service.collect.UserCollectService;
import com.qd.panda.service.score.CarParkEvaluateService;
import com.qd.panda.service.stroke.UserStrokeHistoryService;
import com.qd.system.service.person.AuthTokenService;
import com.qd.system.service.system.SystemSetService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Optional;

/**
 * @author sjk
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ParkStrokeHolderService {
    private final CarParkService carParkService;
    private final CarParkGasStationService carParkGasStationService;
    private final UserCollectService userCollectService;
    private final CarParkEvaluateService carParkEvaluateService;
    private final CarParkAppointmentSetService appointmentSetService;
    private final CarParkImgService carParkImgService;
    private final UserStrokeHistoryService userStrokeHistoryService;

    private final SystemSetService systemSetService;
    private final HkParkInfoService hkParkInfoService;
    private final AuthTokenService authTokenService;


    @Transactional(readOnly = true)
    public PersonCarPark getInfoById(String pId) {
        final CarPark carPark = carParkService.getById(pId);
        if (null == carPark) {
            return null;
        }
        int tripType = 0;
        if (carPark.getParkType().equals(PandaConstant.PARK_TYPE_CHARGING_STATION)) {
            tripType = 1;
        }
        return personCarPark(null, null, pId, true, tripType);
    }

    /**
     * 停车场详情和当前行程详情使用
     *
     * @param plateNumber 车牌号
     * @param userId      用户ID
     * @param parkId      停车场ID
     * @param isHistory   是否抓取行程的历史记录
     * @param tripType    0停车 1充电
     * @return 拼装好的信息
     */
    public PersonCarPark personCarPark(String plateNumber, String userId, String parkId, boolean isHistory, Integer tripType) {
        if (Boolean.FALSE.equals(carParkService.isExistsById(parkId))) {
            throw new ApiException("停车场ID不存在:[" + parkId + "]");
        }
        //收藏ID
        String collectId = null;
        PersonCarPark park = new PersonCarPark();
        CarParkInfoDTO carParkInfo = carParkService.getCarParkInfoByRedis(parkId);
        if (carParkInfo.getParkType().equals(PandaConstant.PARK_TYPE_GAS_STATION)) {
            //加油站
            carParkGasStationService.build(carParkInfo, true, false, true);
        } else if (carParkInfo.getParkType().equals(PandaConstant.PARK_TYPE_CAR_PARK)) {
            //停车场
            if (carParkInfo.getCarParkType().equals(PandaConstant.CAR_PARK_TYPE_1)) {
                //交投的拉取详细信息
                try {
                    HkBaseHttpResp<HkParkInfoResp> resp = hkParkInfoService.parkInfo(carParkInfo.getPId());
                    if (resp.isSuccess()) {
                        carParkService.updateToRedis(carParkInfo.getPId(), null, resp.getData().getTotalParkingSpaceNum(), resp.getData().getLeftParkingSpaceNum());
                        carParkInfo = carParkService.getCarParkInfoByRedis(parkId);
                    } else {
                        log.error("拉取海康停车场详情失败,pid: {},异常信息: {}", carParkInfo.getPId(), resp.getMsg());
                    }
                } catch (Exception e) {
                    log.error("拉取海康停车场详情失败,pid: {}", carParkInfo.getPId(), e);
                }
            }
        }
        park.setCarParkInfo(carParkInfo);
        if (!StringUtils.hasLength(userId)) {
            LoginUser loginUser = authTokenService.getLoginUser(ServletUtil.getRequest());
            if (null != loginUser) {
                userId = loginUser.getUserId();
            }
        }
        if (null != tripType) {
            if (StringUtils.hasLength(userId)) {
                final UserCollect data = userCollectService.getUniqueByUserIdAndParkId(userId, parkId);
                if (null != data) {
                    collectId = data.getCid();
                }
                if (isHistory) {
                    buildHistoryStroke(park, userId, tripType);
                    if (null != park.getHistoryStroke()) {
                        plateNumber = park.getHistoryStroke().getPlateNumber();
                    }
                }
            }
        }
        //车牌号
        if (StringUtils.hasLength(plateNumber)) {
            park.setPlateNumber(plateNumber);
        }
        //是否收藏
        park.setCollect(null == collectId ? 0 : 1);
        park.setCollectId(collectId);
        //停车场评分
        park.setCarParkAvgScore(carParkEvaluateService.avgParkScore(parkId));
        //停车场最后一条评价
        park.setEvaluateContent(carParkEvaluateService.getLastContent(parkId));
        //查询停车场预约信息
        Optional.ofNullable(appointmentSetService.getByIdDto(parkId)).ifPresent(park::setAppointmentSet);
        //停车场介绍图片
        Optional.ofNullable(carParkImgService.getListByPidDto(parkId)).ifPresent(park::setImgList);
        park.setPointDeduction(Optional.ofNullable(systemSetService.getById(PandaConstant.POINT_DEDUCTION)).map(sys -> sys.getValue().replace("\"", "")).orElse(ConstantDto.SF0));
        return park;
    }

    private void buildHistoryStroke(PersonCarPark park, String userId, Integer tripType) {
        if (StringUtils.hasLength(userId)) {
            buildHistoryStroke(park, userStrokeHistoryService.getLastDto(userId, tripType));
        }
    }

    public void buildHistoryStroke(PersonCarPark park, UserStrokeHistoryDTO last) {
        if (null != last && (park.getCarParkInfo().getPId().equals(last.getParkId()))) {
            final CarParkEvaluateDTO query = new CarParkEvaluateDTO();
            query.setSid(last.getSid());
            final Boolean b = carParkEvaluateService.isExists(query);
            query.freeData();
            HistoryStrokeVO historyStrokeVO = new HistoryStrokeVO();
            historyStrokeVO.setParkId(last.getParkId())
                    .setUserEvaluate(Boolean.TRUE.equals(b) ? ConstantDto.SF1 : ConstantDto.SF0)
                    .setAppointmentTime(last.getAppointmentTime())
                    .setPlateNumber(last.getPlateNumber())
                    .setAmount(last.getAmount())
                    .setAmountDisplay(last.getAmountDisplay())
                    .setPayAmount(last.getPayAmount())
                    .setPayAmountDisplay(last.getPayAmountDisplay())
                    .setProcessStatus(last.getProcessStatus())
                    .setProcessStatusDisplay(last.getProcessStatusDisplay())
                    .setSid(last.getSid())
                    .setOutTime(last.getOutTime())
                    .setIntoTime(last.getIntoTime())
                    .setParkIdDisplay(last.getParkIdDisplay())
                    .setTripType(last.getTripType())
                    .setTripTypeDisplay(last.getTripTypeDisplay())
                    .setUserId(last.getUserId());
            park.setHistoryStroke(historyStrokeVO);
        }
    }
}
